package collisions 
{
	import entities.Entity;
	import flash.display.Sprite;
	import flash.geom.Point;
	import flash.geom.Rectangle;
	import flash.utils.describeType;
	import flash.utils.Dictionary;
	import flash.display.Graphics;
	import renderers.Renderer;
	/**
	 * ...
	 * @author Gareth Williams
	 * todo: extract broadphase to interface.
	 */
	public class World
	{
		public static var debugDraw:Sprite = null;
		public static const bodies:Dictionary = new Dictionary(true);
		
		public static function addBody(body:Body):void
		{
			bodies[body] = true;
		}
		public static function removeBody(body:Body):void
		{
			if(World.bodies[body]) bodies[body] = null; //hopefully releases reference for gc...
		}
		public function update():void
		{
			for (var leaf:Object in QuadTree.NODES)
			{
				//recycle with the object pool
				QuadTreePool.checkIn(QuadTree(leaf));
			}
			QuadTree.NODES = new Dictionary(true);
			QuadTree.LEAFS = new Dictionary(true);
			var broadPhase:QuadTree = new QuadTree(0, 0, Constants.SCREEN_WIDTH, Constants.SCREEN_HEIGHT);
			//var broadPhase:QuadTree = QuadTreePool.checkOut(0, 0, Constants.SCREEN_WIDTH, Constants.SCREEN_HEIGHT);	
			
			//construct tree
			for (var collidee:Object in bodies)
			{
				if (bodies[collidee])
				{
					broadPhase.addChild(collidee as Body);//implicitly cast null to false
				}
			}
			
			//check for potential collision groups
			var query:Rectangle =
				new Rectangle(
					0, 0, Constants.MINIMUM_QUADTREE_AREA, Constants.MINIMUM_QUADTREE_AREA);
			var offset:Number = Constants.MINIMUM_QUADTREE_AREA * 0.5;
			
			for (var collider:Object in bodies)
			{
				//centre the rectangle...
				query.x = Body(collider).x - offset;
				query.y = Body(collider).y - offset;
				
				for (var node:Object in QuadTree.LEAFS)
				{
					if (debugDraw !== null)
					{
						var gfx:Graphics = debugDraw.graphics;
						gfx.clear();
						gfx.lineStyle(1, 0xFF0000);
						gfx.drawRect(	QuadTree(node).x, 
										QuadTree(node).y,
										QuadTree(node).width,
										QuadTree(node).height);
					}
					
					if (false == query.intersects(node as Rectangle)) continue;
					
					//todo:final body element is not being checked for some reason...
					var child:LinkedList = QuadTree(node).children.next;
					while (child !== null)
					{
						//use bit flags
						var isSameGroup:Boolean =
							Boolean(Body(child.object).collisionGroup & Body(collider).collisionGroup);
						if (isSameGroup &&
							Entity(child.object).isAlive &&
							Entity(collider).isAlive &&
							child.object !== collider)
						{
							//narrowphase comes from pixel-perfect collision detection algorithm
							//http://anotherearlymorning.com/files/PixelPerfectCollisionDetection.as
							//although the originator of this concept was Andre Michelle
							//if pixel precise (fourth option) is false (default) we just use bounding boxes and save a lot of processing...
							var narrowCollision:Boolean = PixelPerfectCollisionDetection.isColliding(
								Entity(child.object).graphic as Sprite,
								Entity(collider).graphic as Sprite,
								Renderer.rootDisplayObject);
								
							if (true == narrowCollision)
							{
								collider.processCollisionWith(child.object);
								child.object.processCollisionWith(collider);
							}
						}
						child = child.next;
					}
				}
			}
		}
	}
}